<html>
<head>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/JavaScript" src="./js/lib/jsDraw2D.js"></script>
<script type="text/JavaScript" src="./js/lib/svm.js"></script>
<script type="text/JavaScript" src="./js/lib/quadprog.js"></script>
<script type="text/JavaScript" src="./js/drawing.js"></script>
<script type="text/JavaScript" src="./js/lib/math.min.js"></script>
<script type="text/JavaScript" src="./js/TestPlane.js"></script>
<script type="text/JavaScript" src="./js/PLA.js"></script>
<script type="text/JavaScript" src="./js/Linear_Regression.js"></script>
<script type="text/JavaScript" src="./js/Quadratic_Function_Solver.js"></script>

<div id="control">
  <div>
    <label for="N">N = </label>
    <input type="text" name="N" id="N" value="100" />
  </div>
  <div>
    <label for="testTimes">Test times = </label>
    <input type="text" name="testTimes" id="testTimes" value="1000" />
  </div>
  <div>
    <button id="vs">PLA vs SVM</button>
    <button id="vs_times">PLA vs SVM (multiple times)</button>
  </div>
</div>

<div style="position:relative;">
  <div style="position:absolute; width: 350px;">
    <textarea id="status" readonly rows="30" cols="40"></textarea>
  </div>
  <div id="canvas" style="position:absolute; width:500px;height:500px;left:350px" />
</div>

<script type="text/JavaScript">
  var add_w0 = function(point) {
    return [1,
            point[0],
            point[1]];
  };

  window.generateDataSet = function(NumberOfN, plane) {
    var result = [];
    for(var i = 0; i < NumberOfN; i++) {
      var point = plane.randomPoint();
      var output = plane.getOutput(point);
      result.push({point: point, output: output});
    }
    return result;
  }

  window.transformDataSet = function(dataSet, transformFunction) {
    var result = [];
    for(var i in dataSet) {
      result.push({point: transformFunction(dataSet[i].point), output: dataSet[i].output});
    }
    return result;
  }

  window.vs = function(NumberOfN) {
    var plane = new window.TestPlane(-1,1,-1,1);
    var dataSet = window.generateDataSet(NumberOfN, plane);
    var dataSetWithw0 = window.transformDataSet(dataSet, add_w0);

    var pointsArray = [];
    var labelsArray = [];
    for(var i = 0; i < dataSetWithw0.length; i++) {
      pointsArray.push(dataSetWithw0[i].point);
      labelsArray.push(dataSetWithw0[i].output);
    }

    var pla = new window.PLA([0,0,0], function(x) {return Math.sign(x);});
    var svm = new svmjs.SVM();

    pla.trainSet(dataSetWithw0, false);
    svm.train(pointsArray, labelsArray, {kernel: 'linear', C: 1000000, alphatol: 0, maxiter: 100000});

    window.initCanvas();
    window.drawTargetLine(plane);
    window.drawDataSet(dataSet);

    var plaLine = window.weightsToLine(pla._weights, plane);
    window.plotLine(plaLine, greenPen);

    var svm_weights = svm.w;
    svm_weights[0] = svm_weights[0] + svm.b;
    var svmLine = window.weightsToLine(svm_weights, plane);
    window.plotLine(svmLine, pinkPen2);

    var status = 'Eout PLA: ' + '\r\n' + window.getErrorRate(pla._weights, plane) + '\r\n'
               + 'Eout SVM: ' + '\r\n' + window.getErrorRate(svm_weights, plane) + '\r\n';
    $('#status').val(status);
  }

  window.vs_times = function(NumberOfN, times) {
    var times_svm_better = 0;

    for(var k = 0; k < times; k++) {
      var allOutputSame = true;
      var plane;
      var dataSet;

      while(allOutputSame) {
        plane = new window.TestPlane(-1,1,-1,1);
        dataSet = window.generateDataSet(NumberOfN, plane);
        var sumOutput = 0;
        for (var j=0; j < dataSet.length; j++) {
          sumOutput += dataSet[j].output;
        }
        if(Math.abs(sumOutput) != dataSet.length) allOutputSame = false;
      }

      var dataSetWithw0 = window.transformDataSet(dataSet, add_w0);

      var pointsArray = [];
      var labelsArray = [];
      for(var i = 0; i < dataSetWithw0.length; i++) {
        pointsArray.push(dataSetWithw0[i].point);
        labelsArray.push(dataSetWithw0[i].output);
      }

      var pla = new window.PLA([0,0,0], function(x) {return Math.sign(x);});
      var svm = new svmjs.SVM();

      pla.trainSet(dataSetWithw0, false);
      svm.train(pointsArray, labelsArray, {kernel: 'linear', C: 1000000, alphatol: 0, maxiter: 100000});

      var svm_weights = svm.w;
      svm_weights[0] = svm_weights[0] + svm.b;

      if(window.getErrorRate(svm_weights, plane) < window.getErrorRate(pla._weights, plane)) {
        times_svm_better += 1;
      }
    }
    fraction_svm_better =  times_svm_better / times;

    var status = 'SVM better: ' + '\r\n' + fraction_svm_better + '\r\n';
    $('#status').val(status);
  }

  window.getErrorRate = function(weights, plane) {
    var numberOfErrorTestPoint = 100000;
    var errorPointCount = 0;
    for(var i = 0; i < numberOfErrorTestPoint; i++) {
      var testErrorPoint = plane.randomPoint();

      var point = add_w0(testErrorPoint);
      var output = 0;
      for(var j = 0; j < point.length; j++) {
        output += weights[j] * point[j];
      }
      output = math.sign(output);
      if(plane.getOutput(testErrorPoint) !== output) errorPointCount += 1;
    }
    return errorPointCount / numberOfErrorTestPoint;
  }

  window.initCanvas();
  $('#vs').on('click', function() { window.vs($('#N').val()); });
  $('#vs_times').on('click', function() { window.vs_times($('#N').val(), $('#testTimes').val()); });
</script>
</body>
</html>